import {_decorator, Animation, Component, EventMouse, input, Input, Vec3} from 'cc';
import {EventManager} from "db://assets/Scripts/Common/EventManager";
import {EventType} from "db://assets/Scripts/Common/EventType";

const {ccclass, property} = _decorator;

/**
 * 放大常量
 */
export const BLOCK_SIZE = 40;

@ccclass('PlayerController')
export class PlayerController extends Component {
    /**
     * Body动画组件
     */
    private bodyAnimation: Animation = null!;

    /**
     * 是否正在跳跃
     */
    private jumping: boolean = false;
    /**
     * 跳跃的步数
     */
    private jumpStep: number = 0;
    /**
     * 跳跃总时长
     */
    private jumpTime: number = 0.1;
    /**
     * 当前跳跃的时间
     */
    private currentJumpTime: number = 0;
    /**
     * 当前跳跃的速度
     */
    private currentJumpSpeed: number = 0;
    /**
     * 当前位置
     */
    private currentPosition: Vec3 = new Vec3();
    /**
     * 间隔位置
     */
    private deltaPosition: Vec3 = new Vec3();
    /**
     * 目标位置
     */
    private targetPosition: Vec3 = new Vec3();
    /**
     * 得分
     */
    private score: number = 0;

    start() {
        // 初始化动画组件
        let BodyNode = this.node.getChildByName("Body");
        this.bodyAnimation = BodyNode.getComponent(Animation);
    }

    update(deltaTime: number) {
        // 需要跳跃
        if (this.jumping) {
            // 累计跳跃的总时长
            this.currentJumpTime += deltaTime;
            // 跳跃时间是否结束
            if (this.currentJumpTime > this.jumpTime) {
                // 强制设置为目标位置
                this.node.setPosition(this.targetPosition);
                // 完成跳跃
                this.jumping = false;
                // 发送更新分数事件
                EventManager.emit(EventType.SCORE, this.score);
            } else {
                // 获取角色当前位置
                this.node.getPosition(this.currentPosition);
                // 下一帧的位置
                this.deltaPosition.x = this.currentJumpSpeed * deltaTime;
                // 应用这个位移
                Vec3.add(this.currentPosition, this.currentPosition, this.deltaPosition);
                // 设置位置
                this.node.setPosition(this.currentPosition);
            }
        }
    }

    /**
     * 监听鼠标事件
     *
     * @param event 鼠标事件
     */
    onMouseUp(event: EventMouse) {
        if (event.getButton() === EventMouse.BUTTON_LEFT) {
            // 左键，跳一步
            this.jumpByStep(1);
        } else if (event.getButton() === EventMouse.BUTTON_RIGHT) {
            // 右键，跳两步
            this.jumpByStep(2);
        }
    }

    /**
     * 在 jumpByStep 里面计算出角色要移动所必须的信息
     * 在 update 里面执行角色运动的行为
     */
    jumpByStep(step: number) {
        // 正在跳跃
        if (this.jumping) {
            return;
        }

        // 开始跳跃
        this.jumping = true;
        // 记录跳跃步数
        this.jumpStep = step;
        // 重置跳跃时长
        this.currentJumpTime = 0;

        // 计算跳跃时长
        const clipName = step === 1 ? 'oneStep' : 'twoStep';
        const state = this.bodyAnimation.getState(clipName);
        this.jumpTime = state.duration;

        // 计算跳跃需要的速度
        this.currentJumpSpeed = this.jumpStep * BLOCK_SIZE / this.jumpTime;
        // 获取当前角色位置
        this.node.getPosition(this.currentPosition);
        // 计算目标位置
        Vec3.add(this.targetPosition, this.currentPosition, new Vec3(this.jumpStep * BLOCK_SIZE, 0, 0));

        // 动画
        this.bodyAnimation.play(step === 1 ? "oneStep" : "twoStep");

        // 累计得分
        this.score += step;
    }

    /**
     * 是否激活鼠标监听事件
     *
     * @param active 是否激活
     */
    setInputActive(active: boolean) {
        if (active) {
            input.on(Input.EventType.MOUSE_UP, this.onMouseUp, this);
        } else {
            input.off(Input.EventType.MOUSE_UP, this.onMouseUp, this);
        }
    }

    /**
     * 重置
     */
    reset() {
        // 重置分数
        this.score = 0;
    }
}